<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { ref, onMounted } from "vue";
// @ts-ignore
import testPng from '@/assets/test.png'

// 画布
const canvas = ref<any>('');
// 场景
const scene = new THREE.Scene();
// 几何对象
const boxGeometry = new THREE.BoxGeometry(100, 100, 100);
// 材质纹理贴图
const texture = new THREE.TextureLoader().load(testPng);
// 材质
const phongMaterial = new THREE.MeshPhongMaterial({
  color: 0xffffff,
  shininess: 10, // 高光部分的亮度，默认30 - 控制高光反射效果
  specular: 0x111111, // 高光部分的颜色 - 控制高光反射效果
  map: texture, // 纹理贴图
});
// 网格模型Mesh
const mesh = new THREE.Mesh(boxGeometry, phongMaterial);
scene.add(mesh);
// 光源 - 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambientLight);
// 相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(200, 200, 200);
camera.lookAt(0, 0, 0);
// 渲染器
const renderer = new THREE.WebGLRenderer({
  antialias: true, // 抗锯齿
});
// 渲染器 - 像素比率
renderer.setPixelRatio(window.devicePixelRatio);
// 渲染器 - 背景颜色
renderer.setClearColor(0x444444, 1);
// 渲染器 - 大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 控制是否旋转
const controlRotate = {
  rotateY: false,
  rotateX: false,
  rotateZ: false,
  rotateSpeed: 0.001,
};
// 渲染函数
function render() {
  if (controlRotate.rotateY) {
    mesh.rotation.y += controlRotate.rotateSpeed;
  }
  if (controlRotate.rotateX) {
    mesh.rotation.x += controlRotate.rotateSpeed;
  }
  if (controlRotate.rotateZ) {
    mesh.rotation.z += controlRotate.rotateSpeed;
  }
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 相机控件.target属性在OrbitControls.js内部表示相机目标观察点，默认0,0,0
controls.update();

// 实例化一个gui对象 - 可视化改变三维场景
const gui = new GUI();
// 通过 GUI 改变 高光材质 颜色
gui.addColor(phongMaterial, "color").name("材质颜色").onChange((val) => {
  console.log('高光材质 color onchange ', val);
});
// 子菜单 - 旋转
const rotateMenu = gui.addFolder("旋转");
// 菜单默认关闭状态
rotateMenu.close();
// 使用布尔值控制网格模型是否旋转
//@ts-ignore
rotateMenu.add(controlRotate, 'rotateY').name('是否旋转Y轴');
//@ts-ignore
rotateMenu.add(controlRotate, 'rotateX').name('是否旋转X轴');
//@ts-ignore
rotateMenu.add(controlRotate, 'rotateZ').name('是否旋转Z轴');
//@ts-ignore
rotateMenu.add(controlRotate, 'rotateSpeed', 0.001, 1).name('旋转速率').step(0.001);
// 通过GUI改变mesh.position对象的xyz属性
// 子菜单 - 环境光
const ambientLightMenu = gui.addFolder("环境光");
// 菜单默认关闭状态
ambientLightMenu.close();
// @ts-ignore
ambientLightMenu.add(ambientLight, 'intensity', 0, 2.0).name('环境光强度').step(0.1).onChange((val) => {
  console.log(' 环境光强度 onchange event ', val);
});
ambientLightMenu.addColor(ambientLight, "color").name("环境光颜色").onChange((val) => {
  console.log('环境光颜色 color onchange ', val);
});
// gui改变ThreeJs模型位置测试
// 子菜单 - 模型位置
const modePosition = gui.addFolder("模型位置");
// 菜单默认展开状态
modePosition.open();
// 使用两个区间参数生成交互界面拖动条
// @ts-ignore
modePosition.add(mesh.position, 'x', 0, 180).name("网格模型X轴");
// 使用对象生成交互界面下拉菜单
// @ts-ignore
modePosition.add(mesh.position, 'y', {
  下: -100,
  中: 0,
  上: 100,
}).name("网格模型Y轴");
// 使用对象生成交互界面下拉菜单
// @ts-ignore
modePosition.add(mesh.position, 'z', [-300, -200, -100, 0, 100, 200, 300]).name("网格模型Z轴");

// 组件挂载的时候渲染
onMounted(() => {
  canvas.value.appendChild(renderer.domElement);
  render();
});

</script>
